package com.tang.consumer.config;

import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;

import java.io.IOException;
import java.util.Set;

/**
 * @author Tang
 * @classname ClassPathRpcScanner
 * @description [  ]
 * @date 2021/1/24 15:35
 */
public class ClassPathRpcScanner extends ClassPathBeanDefinitionScanner {

    public ClassPathRpcScanner(BeanDefinitionRegistry registry) {
        super(registry);
    }

    @Override
    protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        // 必须先调用这个方法,
        this.restFilter();
        return super.doScan(basePackages);
    }

    /**
     * 调用 isCandidateComponent(MetadataReader metadataReader) 方法时
     * 会使用这里定义的 include,exclude规则
     */
    public void restFilter() {
        // 排除不是接口的类
        addExcludeFilter(new TypeFilter() {
            @Override
            public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
                ClassMetadata classMetadata = metadataReader.getClassMetadata();
                return !classMetadata.isInterface();
            }
        });
        addIncludeFilter(new TypeFilter() {
            @Override
            public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
                return true;
            }
        });
    }


    /**
     * 先调用这个 isCandidateComponent(MetadataReader metadataReader) 实现 include 还是 exclude
     * 必须重写这个方法，，spring是根据这个方法来决定是否加入到 要返回的集合里面 Set<BeanDefinitionHolder>
     * @param beanDefinition
     * @return
     */
    @Override
    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        AnnotationMetadata metadata = beanDefinition.getMetadata();
        //              是个接口            是个完整的类
        return metadata.isInterface() && metadata.isIndependent();
    }
}